// import com.alibaba.druid.sql.ast.SQLExpr_ptr;
// import com.alibaba.druid.sql.ast.SQLHint;
// import com.alibaba.druid.sql.ast.SQLName;
// import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr_ptr;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

#include "SQLLateralViewTableSource.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"
#include "../expr/SQLMethodInvokeExpr.h"

SQLLateralViewTableSource::SQLLateralViewTableSource()
{
  columns = std::make_shared<std::list<SQLName_ptr>>();
}

// @Override
void SQLLateralViewTableSource::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLLateralViewTableSource)))
  {
    acceptChild(visitor, tableSource);
    acceptChild(visitor, std::dynamic_pointer_cast<SQLObject>(method));
    SQLObject_list_ptr tmp = ListTran::tran_class<SQLName, SQLObject>(columns);
    acceptChild(visitor, tmp);
  }
  visitor->endVisit(SharedObject(SQLLateralViewTableSource));
}

SQLTableSource_ptr SQLLateralViewTableSource::getTableSource()
{
  return tableSource;
}

void SQLLateralViewTableSource::setTableSource(SQLTableSource_ptr tableSource)
{
  if (tableSource != nullptr)
  {
    tableSource->setParent(SharedObject(SQLLateralViewTableSource));
  }
  this->tableSource = tableSource;
}

SQLMethodInvokeExpr_ptr SQLLateralViewTableSource::getMethod()
{
  return method;
}

void SQLLateralViewTableSource::setMethod(SQLMethodInvokeExpr_ptr method)
{
  if (method != nullptr)
  {
    method->setParent(SharedObject(SQLLateralViewTableSource));
  }
  this->method = method;
}

SQLName_list_ptr SQLLateralViewTableSource::getColumns()
{
  return columns;
}

void SQLLateralViewTableSource::setColumns(SQLName_list_ptr columns)
{
  this->columns = columns;
}

SQLTableSource_ptr SQLLateralViewTableSource::findTableSource(long alias_hash)
{
  long hash = this->aliasHashCode64();
  if (hash != 0 && hash == alias_hash)
  {
    return SharedObject(SQLLateralViewTableSource);
  }

  for (SQLName_ptr column : *columns)
  {
    if (column->nameHashCode64() == alias_hash)
    {
      return SharedObject(SQLLateralViewTableSource);
    }
  }

  if (tableSource != nullptr)
  {
    return tableSource->findTableSource(alias_hash);
  }

  return nullptr;
}

SQLTableSource_ptr SQLLateralViewTableSource::findTableSourceWithColumn(long columnNameHash, string_ptr columnName, int option)
{
  for (SQLName_ptr column : *columns)
  {
    if (column->nameHashCode64() == columnNameHash)
    {
      return SharedObject(SQLLateralViewTableSource);
    }
  }

  if (tableSource != nullptr)
  {
    return tableSource->findTableSourceWithColumn(columnNameHash, columnName, option);
  }
  return nullptr;
}

// @Override
SQLObject_ptr SQLLateralViewTableSource::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLLateralViewTableSource>(new SQLLateralViewTableSource());
  std::shared_ptr<SQLLateralViewTableSource> x = std::dynamic_pointer_cast<SQLLateralViewTableSource>(clone_tmp);
  // SQLLateralViewTableSource x = new SQLLateralViewTableSource();

  x->setAlias(this->alias);
  x->outer = outer;

  if (this->tableSource != nullptr)
  {
    x->setTableSource(std::dynamic_pointer_cast<SQLTableSource>(this->tableSource->clone()));
  }

  if (this->method != nullptr)
  {
    x->setMethod(std::dynamic_pointer_cast<SQLMethodInvokeExpr>(this->method->clone()));
  }

  for (SQLName_ptr column : *this->columns)
  {
    SQLName_ptr e2 = std::dynamic_pointer_cast<SQLName>(column->clone());
    e2->setParent(x);
    x->getColumns()->push_back(e2);
  }

  if (this->flashback != nullptr)
  {
    x->setFlashback(std::dynamic_pointer_cast<SQLExpr>(this->flashback->clone()));
  }

  if (this->hints != nullptr)
  {
    for (SQLHint_ptr e : *this->hints)
    {
      SQLHint_ptr e2 = std::dynamic_pointer_cast<SQLHint>(e->clone());
      e2->setParent(std::dynamic_pointer_cast<SQLHint>(x));
      x->getHints()->push_back(e2);
    }
  }

  return x;
}

BOOL_ptr SQLLateralViewTableSource::isOuter()
{
  return outer;
}

void SQLLateralViewTableSource::setOuter(BOOL_ptr outer)
{
  this->outer = outer;
}

SQLExpr_ptr SQLLateralViewTableSource::getOn()
{
  return on;
}

void SQLLateralViewTableSource::setOn(SQLExpr_ptr on)
{
  this->on = on;
}
